package it.sephiroth.android.library.imagezoom;

import java.util.ArrayList;
import android.content.Context;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ViewConfiguration;
import android.view.ViewGroup.LayoutParams;
import android.widget.AbsoluteLayout;
import android.widget.ImageButton;

public class ImageViewTouch extends ImageViewTouchBase {
	static final float MIN_ZOOM = 0.9f;

	protected ScaleGestureDetector mScaleDetector;

	protected GestureDetector mGestureDetector;

	protected int mTouchSlop;

	protected float mCurrentScaleFactor;

	protected float mScaleFactor;

	protected int mDoubleTapDirection;

	protected GestureListener mGestureListener;

	protected ScaleListener mScaleListener;

	public ImageViewTouch(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	protected void init() {
		super.init();
		mTouchSlop = ViewConfiguration.getTouchSlop();
		mGestureListener = new GestureListener();
		mScaleListener = new ScaleListener();
		mScaleDetector = new ScaleGestureDetector(getContext(), mScaleListener);
		mGestureDetector = new GestureDetector(getContext(), mGestureListener, null, true);
		mCurrentScaleFactor = 1f;
		mDoubleTapDirection = 1;
	}

	@Override
	public void setImageRotateBitmapReset(RotateBitmap bitmap, boolean reset) {
		super.setImageRotateBitmapReset(bitmap, reset);
		mScaleFactor = getMaxZoom() / 3;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		mScaleDetector.onTouchEvent(event);
		if (!mScaleDetector.isInProgress()) mGestureDetector.onTouchEvent(event);
		int action = event.getAction();
		switch (action & MotionEvent.ACTION_MASK) {
			case MotionEvent.ACTION_UP:
				if (getScale() < 1f) {
					zoomTo(1f, 50);
				}
				break;
		}
		return true;
	}

	@Override
	protected void onZoom(float scale) {
		super.onZoom(scale);
		if (!mScaleDetector.isInProgress()) mCurrentScaleFactor = scale;
	}

	protected float onDoubleTapPost(float scale, float maxZoom) {
		if (mDoubleTapDirection == 1) {
			if ( (scale + (mScaleFactor * 2)) <= maxZoom) {
				return scale + mScaleFactor;
			} else {
				mDoubleTapDirection = -1;
				return maxZoom;
			}
		} else {
			mDoubleTapDirection = 1;
			return 1f;
		}
	}

	class GestureListener extends GestureDetector.SimpleOnGestureListener {
		@Override
		public boolean onDoubleTap(MotionEvent e) {
			float scale = getScale();
			float targetScale = scale;
			targetScale = onDoubleTapPost(scale, getMaxZoom());
			targetScale = Math.min(getMaxZoom(), Math.max(targetScale, MIN_ZOOM));
			mCurrentScaleFactor = targetScale;
			//Log.d("ZOOMABLE", "ZOOM WITH SCALE :"+ targetScale + " %" + " CENTER: (" + e.getX() + ":" + e.getY()+")");
			zoomTo(targetScale, e.getX(), e.getY(), 200);
			invalidate();
			return super.onDoubleTap(e);
		}

		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
			if (e1 == null || e2 == null) return false;
			if (e1.getPointerCount() > 1 || e2.getPointerCount() > 1) return false;
			if (mScaleDetector.isInProgress()) return false;
			if (getScale() == 1f) return false;
			//Log.d("ZOOMABLE", "SCROLL :"+ " DIFF: (" + -distanceX + ":" + -distanceY +")");
			scrollBy(-distanceX, -distanceY);
			invalidate();
			return super.onScroll(e1, e2, distanceX, distanceY);
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
			if (e1.getPointerCount() > 1 || e2.getPointerCount() > 1) return false;
			if (mScaleDetector.isInProgress()) return false;
			float diffX = e2.getX() - e1.getX();
			float diffY = e2.getY() - e1.getY();
			if (Math.abs(velocityX) > 800 || Math.abs(velocityY) > 800) {
				//Log.d("ZOOMABLE", "Fling :"+ " DIFF: (" + diffX/2 + ":" + diffY/2 +")");
				scrollBy(diffX / 2, diffY / 2, 300);
				invalidate();
			}
			return super.onFling(e1, e2, velocityX, velocityY);
		}
	}
	class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
		@SuppressWarnings("unused")
		@Override
		public boolean onScale(ScaleGestureDetector detector) {
			if(!detector.isInProgress())
				return false;
			float span = detector.getCurrentSpan() - detector.getPreviousSpan();
			float targetScale = mCurrentScaleFactor * detector.getScaleFactor();
			if (true) {
				targetScale = Math.min(getMaxZoom(), Math.max(targetScale, MIN_ZOOM));
				zoomTo(targetScale, detector.getFocusX(), detector.getFocusY());
				mCurrentScaleFactor = Math.min(getMaxZoom(), Math.max(targetScale, MIN_ZOOM));
				mDoubleTapDirection = 1;
				invalidate();
				return true;
			}
			return false;
		}
	}
}
